<template>
  <div class="app-container">
    <!-- 操作日志查询表单 -->
    <el-form :model="queryParams" ref="queryForm" :inline="true" label-width="68px">
      <el-form-item label="操作地址" prop="operIp">
        <el-input
          v-model="queryParams.operIp"
          placeholder="请输入操作地址"
          clearable
          style="width: 200px"
          @keyup.enter="handleQuery"
        />
      </el-form-item>
      <el-form-item label="系统模块" prop="title">
        <el-input
          v-model="queryParams.title"
          placeholder="请输入系统模块"
          clearable
          style="width: 200px"
          @keyup.enter="handleQuery"
        />
      </el-form-item>
      <el-form-item label="操作人员" prop="operName">
        <el-input
          v-model="queryParams.operName"
          placeholder="请输入操作人员"
          clearable
          style="width: 200px"
          @keyup.enter="handleQuery"
        />
      </el-form-item>
      <el-form-item label="类型" prop="businessType">
        <el-select v-model="queryParams.businessType" placeholder="操作类型" clearable style="width: 200px">
          <el-option v-for="item in operType" :key="item.dictValue" :label="item.dictLabel" :value="item.dictValue" />
        </el-select>
      </el-form-item>
      <el-form-item label="状态" prop="status">
        <el-select v-model="queryParams.status" placeholder="操作状态" clearable style="width: 200px">
          <el-option v-for="item in operStatus" :key="item.dictValue" :label="item.dictLabel" :value="item.dictValue" />
        </el-select>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="handleQuery">搜索</el-button>
        <el-button @click="resetQuery">重置</el-button>
        <el-button type="danger" plain :disabled="!ids.length" @click="handleDelete" v-p="['monitor:operlog:remove']"
          >删除</el-button
        >
        <el-button type="danger" plain @click="handleClean" v-p="['monitor:operlog:remove']">清空</el-button>
      </el-form-item>
    </el-form>
    <!-- 操作日志表格 -->
    <el-table
      ref="tables"
      v-loading="loading"
      :data="list"
      @selection-change="handleSelectionChange"
      :default-sort="defaultSort"
      @sort-change="handleSortChange"
      height="90%"
    >
      <el-table-column type="selection" width="50" align="center" />
      <el-table-column label="日志编号" align="center" prop="operId" />
      <el-table-column label="系统模块" align="center" prop="title" :show-overflow-tooltip="true" />
      <el-table-column label="操作类型" align="center" prop="businessType">
        <template v-slot="scope">
          <el-tag v-if="scope.row.businessType === 1" type="primary">新增</el-tag>
          <el-tag v-if="scope.row.businessType === 2" type="danger">删除</el-tag>
          <el-tag v-if="scope.row.businessType === 3" type="success">修改</el-tag>
          <el-tag v-if="scope.row.businessType === 4" type="danger">导出</el-tag>
          <el-tag v-if="scope.row.businessType === 5" type="danger">其他</el-tag>
        </template>
      </el-table-column>
      <el-table-column label="操作人员" align="center" prop="operName" width="110" :show-overflow-tooltip="true" sortable />
      <el-table-column label="操作地址" align="center" prop="operIp" width="130" :show-overflow-tooltip="true" />
      <el-table-column label="操作地点" align="center" prop="operLocation" :show-overflow-tooltip="true" />
      <el-table-column label="操作状态" align="center" prop="status">
        <template v-slot="scope">
          <el-tag v-if="scope.row.status === 0" type="success">成功</el-tag>
          <el-tag v-if="scope.row.status === 1" type="danger">失败</el-tag>
        </template>
      </el-table-column>
      <el-table-column label="操作日期" align="center" prop="operTime" width="180" sortable>
        <template v-slot="scope">
          <span>{{ scope.row.operTime }}</span>
        </template>
      </el-table-column>
      <el-table-column label="消耗时间" align="center" prop="costTime" width="110" :show-overflow-tooltip="true" sortable>
        <template v-slot="scope">
          <span>{{ scope.row.costTime }}毫秒</span>
        </template>
      </el-table-column>
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
        <template v-slot="scope">
          <el-button type="primary" link @click="handleView(scope.row)" v-p="['monitor:operlog:query']">详细</el-button>
        </template>
      </el-table-column>
    </el-table>
    <!-- 分页组件 -->
    <Pagination
      :total="total"
      v-model:page="queryParams.pageNum"
      v-model:limit="queryParams.pageSize"
      @update:page="handlePageChange"
      @update:limit="handlePageSizeChange"
    />
    <!-- 操作日志详细 -->
    <el-dialog title="操作日志详细" v-model="open" width="1000px" append-to-body :draggable="true">
      <el-form ref="formRef" :model="form" label-width="100px">
        <el-row>
          <el-col :span="12">
            <el-form-item label="操作模块：">{{ form.title }} / {{ typeFormat(form) }}</el-form-item>
            <el-form-item label="登录信息：">{{ form.operName }} / {{ form.operIp }} / {{ form.operLocation }}</el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="请求地址：">{{ form.operUrl }}</el-form-item>
            <el-form-item label="请求方式：">{{ form.requestMethod }}</el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="操作方法：">{{ form.method }}</el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="请求参数：">
              <div style="max-height: 200px; overflow: auto">
                {{ form.operParam }}
              </div>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="返回参数：">{{ form.jsonResult }}</el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="操作状态：">
              <div v-if="form.status === 0">正常</div>
              <div v-else-if="form.status === 1">失败</div>
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="消耗时间：">{{ form.costTime }}毫秒</el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="操作时间：">{{ form.operTime }}</el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="异常信息：" v-if="form.status === 1">{{ form.errorMsg }}</el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <template #footer>
        <div class="dialog-footer" style="text-align: right">
          <el-button @click="open = false">关 闭</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import type { DeptOperation, DictionaryData } from "@/typings";
import type { FormInstance } from "element-plus";
import { ref, onMounted } from "vue";
import { cleanOperLogApi, delOperLogApi, getDictDataTypeApi, getOperLogListApi } from "@/api";
import { ElMessage, ElMessageBox } from "element-plus";
import Pagination from "@/components/pagination/Pagination.vue";

const ids = ref<number[]>([]);
const operType = ref<DictionaryData[]>([]);
const operStatus = ref<DictionaryData[]>([]);
const list = ref<DeptOperation[]>([]);
const total = ref(0);
const loading = ref(false);
const open = ref(false);
const form = ref<Partial<DeptOperation>>({});
const queryForm = ref<FormInstance>();
const queryParams = ref({
  operIp: "",
  title: "",
  operName: "",
  businessType: "",
  status: "",
  pageNum: 1,
  pageSize: 10
});
// 执行查询操作
const handleQuery = () => {
  queryParams.value.pageNum = 1;
  getOperLogList();
};
// 重置查询条件
const resetQuery = () => {
  queryForm.value?.resetFields();
  getOperLogList();
};
// 删除选中的日志数据
const handleDelete = () => {
  ElMessageBox.confirm("确定删除所勾选的日志数据吗？删除之后数据将无法恢复", "系统提示", {
    type: "warning"
  }).then(async () => {
    try {
      const res = await delOperLogApi(ids.value.join(","));
      if (res.code === 200) {
        ElMessage.success("删除成功");
        getOperLogList();
        return;
      }
      ElMessage.error(res.message);
    } catch (error) {
      console.error("删除操作日志失败");
    }
  });
};
// 清空所有操作日志
const handleClean = async () => {
  try {
    const res = await cleanOperLogApi();
    if (res.code === 200) {
      ElMessage.success("清空成功");
      getOperLogList();
      return;
    }
    ElMessage.error(res.message);
  } catch (error) {
    console.error("清空操作日志失败");
  }
};
// 查看日志详细信息
const handleView = (row: DeptOperation) => {
  open.value = true;
  form.value = { ...row };
};
// 处理选择变化
const handleSelectionChange = (data: DeptOperation[]) => {
  ids.value = data.map((item: DeptOperation) => item.operId);
};
// 处理排序变化
const handleSortChange = () => {};
const defaultSort: any = ref({ prop: "operTime", order: "descending" });

// 处理页码变化
const handlePageChange = (page: number) => {
  queryParams.value.pageNum = page;
  getOperLogList();
};
// 处理每页条数变化
const handlePageSizeChange = (size: number) => {
  queryParams.value.pageSize = size;
  getOperLogList();
};

// 获取字典数据
const getDictDataType = async () => {
  try {
    const res = await getDictDataTypeApi("sys_oper_type");
    const response = await getDictDataTypeApi("sys_common_status");
    if (res.code === 200) {
      operType.value = res.data;
    } else {
      ElMessage.error(res.message);
    }
    if (response.code === 200) {
      operStatus.value = response.data;
    } else {
      ElMessage.error(response.message);
    }
  } catch (error) {
    console.error("获取字典数据类型失败");
  }
};

// 回显数据字典
const selectDictLabel = (datas: any, value: number) => {
  if (value === undefined) {
    return "";
  }
  const actions = [];
  Object.keys(datas).some((key) => {
    if (datas[key].value == "" + value) {
      actions.push(datas[key].label);
      return true;
    }
  });
  if (actions.length === 0) {
    actions.push(value);
  }
  return actions.join("");
};
// 格式化操作类型
const typeFormat = (row: any) => {
  return selectDictLabel(operType.value, row.businessType);
};

// 获取操作日志列表
const getOperLogList = async () => {
  try {
    loading.value = true;
    const res = await getOperLogListApi(queryParams.value);
    if (res.code === 200) {
      list.value = res.data;
      total.value = res.total as number;
      return;
    }
    ElMessage.error(res.message);
  } catch (error) {
    console.error("获取操作日志列表失败");
  } finally {
    loading.value = false;
  }
};
// 组件挂载后获取操作日志和字典数据
onMounted(() => {
  getOperLogList();
  getDictDataType();
});
</script>

<style lang="scss" scoped>
.app-container {
  width: 100%;
}
</style>
